/*
 * Copyright 2016-2017 lei.xu<xulei2008xulei@163.com>.
 *  
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *  
 *      http://www.apache.org/licenses/LICENSE-2.0
 *  
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.san21go.jfinfunc.financ.norm;

import java.util.List;
import java.util.Map.Entry;
import java.util.TreeMap;

import org.san21go.jfinfunc.AbstractFunction;
import org.san21go.jfinfunc.FinFuncRuntimeException;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Ordering;

/**
 * 最大回撤率指标
 * 
 * Max Drawdown=Max(Px−Py)/Px ; Px,Py=策略某日资产的总价值，y>x
 * 
 * @author xulei
 *
 */
public class MaxDrawdownRatio extends AbstractFunction<Double> {

	private double[] pValues;
	private String[] pDates;

	public MaxDrawdownRatio(double[] pValues, String[] pDates) {
		this.pValues = pValues;
		this.pDates = pDates;
	}

	@Override
	public Double evaluate() {
		if (pValues == null || pDates == null || pValues.length == 0) {
			throw new FinFuncRuntimeException("参数错误");
		}
		if (pValues.length != pDates.length) {
			throw new FinFuncRuntimeException("参数错误");
		}
		TreeMap<String, Double> treeMap = Maps.newTreeMap(Ordering.natural());
		// 排序处理
		for (int i = 0; i < pValues.length; i++) {
			treeMap.put(pDates[i], pValues[i]);
		}

		List<Entry<String, Double>> list = Lists.newArrayList(treeMap.entrySet().iterator());

		double maxDiff = 0;
		Entry<String, Double> maxEntry = null;
		Entry<String, Double> minEntry = null;
		for (int i = 0; i < list.size(); i++) {
			double value1 = list.get(i).getValue();
			// 起始位置为 i+1,仅需要考虑大于起始日期的数据
			for (int j = i + 1; j < list.size(); j++) {
				double value2 = list.get(j).getValue();
				double diff = value1 - value2;

				if (Double.compare(diff, maxDiff) > 0) {
					maxDiff = diff;
					maxEntry = list.get(i);
					minEntry = list.get(j);
				}
			}
		}
		if (maxEntry == null || minEntry == null) {
			return 0D;
		}
		if (Double.compare(maxEntry.getValue(), 0) == 0) {
			return 0D;
		}

		return maxDiff / maxEntry.getValue();
	}

}
